/*=========================================================================

Program:   Virtual Surgery
Language:  C++
Date:      2009-9-1
Version:   0.1
Mail:		   nelfylee@gmail.com

Copyright (c) 2009 Nelfy Lee. All rights reserved.

=========================================================================*/
#ifndef _SEGMENTATION_PANELS_H_
#define _SEGMENTATION_PANELS_H_

#include "Source.h"
#include "ControlPanelBase.h"
#include "ControlPanelDock.h"
#include "DisplayModel.h"

#include "ui_VesselProcessing.h"
#include "ui_SegConfidenceConnected.h"
#include "ui_SegThresholdLevelSet.h"
#include "itkConnectedThresholdImageFilter.h"


#include "SegmentationThreads.h"

#include <QDebug>


class VesselProcessingPanel : public ControlPanelBase
{
	Q_OBJECT
public:
	VesselProcessingPanel(QWidget *parent);
	~VesselProcessingPanel();

	void setSource(const QModelIndex& index);

private slots:
	void slotThresholdChanged();
	void slotPVSegmentation();
	void slotArterySegmentation();
	void slotOtsuThresholding();
	void slotHessianProcessing();
	bool slotExtractMaxROI();

private:
	template<class TPixelType>
	void createCTThread()
	{
		typedef itk::Image<TPixelType, 3> TImageType;
		RegionGrowingThread<TPixelType> *m_workingThread = new RegionGrowingThread<TPixelType>(currentSource(), thConnectedThresholding);

		QStringList sl = m_displayModel->currentSeed().split(",");
		if ( sl.count() != 3)
		{
			qDebug() << "seed error";
			return;
		}
		
		typename TImageType::IndexType seed;
		seed[0] = sl.at(0).toInt();
		seed[1] = sl.at(1).toInt();
		seed[2] = sl.at(2).toInt();

		m_workingThread->setThreshold(m_ui.slider_lower->value(), m_ui.slider_upper->value());
		m_workingThread->addSeed(seed);
		m_workingThread->setReplaceValue(m_ui.spin_replaceValue->value());

		connect(m_workingThread, SIGNAL(emitProgressStart(QString)), m_parent, SLOT(slotProgressStart(QString)));
		connect(m_workingThread, SIGNAL(emitProgressUpdate(int)), m_parent, SLOT(slotProgressUpdate(int)));
		connect(m_workingThread, SIGNAL(emitProgressDone()), m_parent, SLOT(slotProgressDone()));
		//connect(m_workingThread, SIGNAL(finished()), SLOT(slotThreadFinished()));

		m_workingThread->start();
	}

	template<class TPixelType>
	void createThread_ExtractMAXROI()
	{
		typedef itk::Image<TPixelType, 3> TImageType;
		RegionGrowingThread<TPixelType> *m_workingThread = new RegionGrowingThread<TPixelType>(currentSource(), thExtractMAXROI);

		connect(m_workingThread, SIGNAL(emitProgressStart(QString)), m_parent, SLOT(slotProgressStart(QString)));
		connect(m_workingThread, SIGNAL(emitProgressUpdate(int)), m_parent, SLOT(slotProgressUpdate(int)));
		connect(m_workingThread, SIGNAL(emitProgressDone()), m_parent, SLOT(slotProgressDone()));
		//connect(m_workingThread, SIGNAL(finished()), SLOT(slotThreadFinished()));

		m_workingThread->start();
	}


	template<class TPixelType>
	void createCCThread()
	{
		typedef itk::Image<TPixelType, 3> TImageType;
		RegionGrowingThread<TPixelType> *m_workingThread = new RegionGrowingThread<TPixelType>(currentSource(), thConfidenceConnected);

		QStringList sl = m_displayModel->currentSeed().split(",");
		if ( sl.count() != 3)
		{
			qDebug() << "seed error";
			return;
		}

		typename TImageType::IndexType seed;
		seed[0] = sl.at(0).toInt();
		seed[1] = sl.at(1).toInt();
		seed[2] = sl.at(2).toInt();

		m_workingThread->setCCPara(m_ui.spin_ccMultiplier->value(), m_ui.spin_ccIteration->value());
		m_workingThread->addSeed(seed);
		m_workingThread->setReplaceValue(m_ui.spin_replaceValue->value());

		connect(m_workingThread, SIGNAL(emitProgressStart(QString)), m_parent, SLOT(slotProgressStart(QString)));
		connect(m_workingThread, SIGNAL(emitProgressUpdate(int)), m_parent, SLOT(slotProgressUpdate(int)));
		connect(m_workingThread, SIGNAL(emitProgressDone()), m_parent, SLOT(slotProgressDone()));
		//connect(m_workingThread, SIGNAL(finished()), SLOT(slotThreadFinished()));

		m_workingThread->start();
	}

	template<class TPixelType>
	void createOtsuThread()
	{
		typedef itk::Image<TPixelType, 3> TImageType;
		RegionGrowingThread<TPixelType> *m_workingThread = new RegionGrowingThread<TPixelType>(currentSource(), thOtsuThresholding);

		connect(m_workingThread, SIGNAL(emitProgressStart(QString)), m_parent, SLOT(slotProgressStart(QString)));
		connect(m_workingThread, SIGNAL(emitProgressUpdate(int)), m_parent, SLOT(slotProgressUpdate(int)));
		connect(m_workingThread, SIGNAL(emitProgressDone()), m_parent, SLOT(slotProgressDone()));

		m_workingThread->start();
	}

	template<class TPixelType>
	void createHessianThread()
	{
		typedef itk::Image<TPixelType, 3> TImageType;
		RegionGrowingThread<TPixelType> *m_workingThread = new RegionGrowingThread<TPixelType>(currentSource(), thHessianProcessing);

		m_workingThread->SetHessianParameters(m_ui.spin_sigma->value(), m_ui.spin_a1->value(), m_ui.spin_a2->value());

		connect(m_workingThread, SIGNAL(emitProgressStart(QString)), m_parent, SLOT(slotProgressStart(QString)));
		connect(m_workingThread, SIGNAL(emitProgressUpdate(int)), m_parent, SLOT(slotProgressUpdate(int)));
		connect(m_workingThread, SIGNAL(emitProgressDone()), m_parent, SLOT(slotProgressDone()));

		m_workingThread->start();
	}
private:
	Ui::ConnectedThreshold m_ui;
};




class LiverProcessingPanel : public ControlPanelBase
{
	Q_OBJECT
public:
	LiverProcessingPanel(QWidget *parent);
	~LiverProcessingPanel();

	void setDisplayModel(DisplayModel* dm);
	void setSource(const QModelIndex& index);

private slots:
	void run();
	void slotThresholdChanged();

protected:
	Ui::ThresholdLevelSet m_ui;

private:
		template<class TPixelType>
		void createThreads()
		{
			ThresholdLevelSetThread<TPixelType> *thread = new ThresholdLevelSetThread<TPixelType>(currentSource());

			QStringList sl = m_displayModel->currentSeed().split(",");
			if ( sl.count() != 3)
			{
				qDebug() << "seed error";
				return;
			}

			ImageShort3D::IndexType seed;
			seed[0] = sl.at(0).toInt();
			seed[1] = sl.at(1).toInt();
			seed[2] = sl.at(2).toInt();

			if ( m_ui.btn_2d->isChecked())
				thread->setMode(lsm2DSlice);
			else
				thread->setMode(lsm3DVolume);

			
			TLS_PARA para;
// 			para.tlsCurv = m_ui.spin_curv->value();
// 			para.tlsProp = m_ui.spin_prop->value();
// 			para.tlsDist = m_ui.spin_dist->value();
// 			para.tlsISO = m_ui.spin_iso->value();
// 			para.tlsRMS = m_ui.spin_rms->value();
// 			para.tlsIteration = m_ui.spin_iteration->value();

			para.tlsCurv = 15.0;
			para.tlsProp = 0.5;
			para.tlsDist = 2.0;
			para.tlsISO = 0.5;
			para.tlsRMS = 0.02;
			para.tlsIteration = 4000;


			if ( m_ui.cb_toLeft->isChecked())
				para.tlsGoLeft = m_ui.spin_toLeft->value();
			else
				para.tlsGoLeft = -1;

			if ( m_ui.cb_toRight->isChecked())
				para.tlsGoRight = m_ui.spin_toRight->value();
			else
				para.tlsGoRight = -1;

			//para.tlsGoLeft = m_ui.btn_goLeft->isChecked() ? 1: 0;
			//para.tlsGoRight = m_ui.btn_goRight->isChecked() ? 1 : 0;

			thread->setParameters(para);
			thread->setThreshold(m_ui.slider_lower->value(), m_ui.slider_upper->value());
			thread->addSeed(seed);

			connect(thread, SIGNAL(emitProgressStart(QString)), m_parent, SLOT(slotProgressStart(QString)));
			connect(thread, SIGNAL(emitProgressUpdate(int)), m_parent, SLOT(slotProgressUpdate(int)));
			connect(thread, SIGNAL(emitProgressDone()), m_parent, SLOT(slotProgressDone()));
			//connect(thread, SIGNAL(finished()), SLOT(slotThreadFinished()));

// 			connect(thread, SIGNAL(emitStartRealTimeSlicing(Source*)), m_display, SLOT(slotStartRealTimeSlicing(Source*)));
// 			connect(thread, SIGNAL(emitStopRealTimeSlicing()), m_display, SLOT(slotStopRealTimeSlicing()));
// 			connect(thread, SIGNAL(emitUpdateSlicing()), m_display, SLOT(slotUpdateSlicing()));

			connect(thread, SIGNAL(emitStartRealTimeSlicing(Source*)),m_displayModel, SLOT(slotStartRealTimeSlicing(Source*)));
			connect(thread, SIGNAL(emitStopRealTimeSlicing()), m_displayModel, SLOT(slotStopRealTimeSlicing()));
			connect(thread, SIGNAL(emitUpdateSlicing(vtkImageData*, int)), m_displayModel, SLOT(slotUpdateRealTimeSlicing(vtkImageData*, int)));

			thread->start();
		}
};



#endif



